package dao

import (
	"chat_srv/basic/config"
	chat "chat_srv/basic/proto"
	"chat_srv/handler/model"
	"chat_srv/untils"
	"context"
	"fmt"
	"golang.org/x/exp/rand"
	"log"
	"strings"
	"time"
)

// 获取随机问题
func GetRandomQuestion(_ context.Context, in *chat.GetRandomQuestionReq) (*model.ImIcebreakerQuestion, error) {
	// 查询数据库中的全部问题
	var question model.ImIcebreakerQuestion
	questions, err := question.GetQuestion()
	if err != nil {
		return nil, fmt.Errorf("查询问题失败：%w", err)
	}
	if len(questions) == 0 {
		return nil, fmt.Errorf("未找到可用的破冰问题")
	}

	// 随机选择一个问题
	rand.Seed(uint64(time.Now().UnixNano()))
	index := rand.Intn(len(questions))
	selectedQuestion := questions[index]

	return selectedQuestion, nil
}

// 按分类/兴趣获取随机问题
// 根据用户提供的兴趣分类，从题库中“按照权重随机”返回一套破冰问题
func GetRandomQuestionByCategory(_ context.Context, in *chat.GetRandomQuestionByCategoryReq) (*model.ImIcebreakerQuestion, error) {
	// 参数校验
	if in == nil || len(in.Category) == 0 {
		return nil, fmt.Errorf("分类参数不能为空")
	}
	// 查询数据库中的全部问题
	var question model.ImIcebreakerQuestion
	allQuestions, err := question.GetQuestion()
	if err != nil {
		return nil, fmt.Errorf("查询问题失败：%w", err)
	}
	if len(allQuestions) == 0 {
		return nil, fmt.Errorf("未找到可用的破冰问题")
	}

	// 为每个问题计算兴趣匹配权重
	weightedQuestions := make([]struct {
		question *model.ImIcebreakerQuestion
		weight   int
	}, 0, len(allQuestions))

	for _, q := range allQuestions {
		weight := calculateInterestWeight(q.Category, []string{in.Category})
		if weight > 0 {
			weightedQuestions = append(weightedQuestions, struct {
				question *model.ImIcebreakerQuestion
				weight   int
			}{q, weight})
		}
	}

	if len(weightedQuestions) == 0 {
		return nil, fmt.Errorf("未找到与兴趣匹配的破冰问题")
	}

	// 根据权重随机选择
	totalWeight := 0
	for _, wq := range weightedQuestions {
		totalWeight += wq.weight
	}
	rand.Seed(uint64(time.Now().UnixNano()))
	randomWeight := rand.Intn(totalWeight)

	currentWeight := 0
	for _, wq := range weightedQuestions {
		currentWeight += wq.weight
		if randomWeight < currentWeight {
			return wq.question, nil
		}
	}

	return weightedQuestions[len(weightedQuestions)-1].question, nil
}

// 计算兴趣匹配权重
func calculateInterestWeight(questionCategory string, userCategories []string) int {
	for _, userCategory := range userCategories {
		if questionCategory == userCategory {
			return 10 // 完全匹配，高权重
		}
		// 可以添加部分匹配逻辑
		if strings.Contains(questionCategory, userCategory) ||
			strings.Contains(userCategory, questionCategory) {
			return 5 // 部分匹配，中等权重
		}
	}
	return 1 // 默认权重，确保所有问题都有机会被选中
}

// 表情包推荐
func GetRandomStickerByCategory(_ context.Context, in *chat.GetRandomStickerByCategoryReq) ([]*model.ImSticker, error) {
	// 提取关键词
	keywords := untils.ExtractKeywords(in.Context)

	// 根据关键词查找表情包
	stickers, err := FindByKeywords(keywords)
	if err != nil {
		return nil, fmt.Errorf("根据关键词查找表情包失败: %w", err)
	}

	// 如果匹配结果为空，补充热门表情包
	if len(stickers) == 0 {
		var sticker model.ImSticker
		hotStickers, err := sticker.GetHotSticker()
		if err != nil {
			// 记录日志但继续返回已有结果
			log.Printf("获取热门表情包失败: %v", err)
			return stickers, nil
		}
		stickers = append(stickers, hotStickers...)
	}

	return stickers, nil
}

// 根据关键词查找表情包
func FindByKeywords(keywords []string) ([]*model.ImSticker, error) {
	// 参数校验
	if len(keywords) == 0 {
		// 查询热门表情包
		return getHotStickers()
	}

	var stickers []*model.ImSticker

	// 构建查询条件
	query := config.DB

	// 为每个关键词添加OR条件
	orConditions := make([]string, 0, len(keywords))
	args := make([]interface{}, 0, len(keywords))

	for _, kw := range keywords {
		// 使用 LIKE 在 key_words 字段中进行模糊匹配
		orConditions = append(orConditions, "key_words LIKE ?")
		args = append(args, "%"+kw+"%")
	}

	if len(orConditions) > 0 {
		query = query.Where(strings.Join(orConditions, " OR "), args...)
	}

	// 按使用次数排序并限制数量
	err := query.Order("usage_count DESC").Limit(5).Find(&stickers).Error
	if err != nil {
		return nil, fmt.Errorf("查询表情包失败: %w", err)
	}

	return stickers, nil
}

// 提取获取热门表情包的逻辑为独立函数
func getHotStickers() ([]*model.ImSticker, error) {
	var sticker model.ImSticker
	hotStickers, err := sticker.GetHotSticker()
	if err != nil {
		return nil, fmt.Errorf("查询热门表情包失败: %w", err)
	}

	return hotStickers, nil
}
